\subsection{\CapitalPICcode}
\myindex{\PICcode}
\myindex{Linux}
\label{sec:PIC}

While analyzing Linux shared (.so) libraries, one may frequently spot this code pattern:

\begin{lstlisting}[caption=libc-2.17.so x86,style=customasmx86]
.text:0012D5E3 __x86_get_pc_thunk_bx proc near         ; CODE XREF: sub_17350+3
.text:0012D5E3                                         ; sub_173CC+4 ...
.text:0012D5E3                 mov     ebx, [esp+0]
.text:0012D5E6                 retn
.text:0012D5E6 __x86_get_pc_thunk_bx endp

...

.text:000576C0 sub_576C0       proc near               ; CODE XREF: tmpfile+73

...

.text:000576C0                 push    ebp
.text:000576C1                 mov     ecx, large gs:0
.text:000576C8                 push    edi
.text:000576C9                 push    esi
.text:000576CA                 push    ebx
.text:000576CB                 call    __x86_get_pc_thunk_bx
.text:000576D0                 add     ebx, 157930h
.text:000576D6                 sub     esp, 9Ch

...

.text:000579F0                 lea     eax, (a__gen_tempname - 1AF000h)[ebx] ; "__gen_tempname"
.text:000579F6                 mov     [esp+0ACh+var_A0], eax
.text:000579FA                 lea     eax, (a__SysdepsPosix - 1AF000h)[ebx] ; "../sysdeps/posix/tempname.c"
.text:00057A00                 mov     [esp+0ACh+var_A8], eax
.text:00057A04                 lea     eax, (aInvalidKindIn_ - 1AF000h)[ebx] ; "! \"invalid KIND in __gen_tempname\""
.text:00057A0A                 mov     [esp+0ACh+var_A4], 14Ah
.text:00057A12                 mov     [esp+0ACh+var_AC], eax
.text:00057A15                 call    __assert_fail
\end{lstlisting}


All pointers to strings are corrected by some constants and the value in \EBX,
which is calculated at the beginning of each function.

This is the so-called \ac{PIC}, it is intended to be executable if placed at any random point of memory, that is why it cannot contain any absolute memory addresses.

\ac{PIC} was crucial in early computer systems and is still crucial today in embedded systems without 
virtual memory support (where all processes are placed in a single continuous memory block).

It is also still used in *NIX systems for shared libraries, since they 
are shared across many processes while loaded in memory only once.
But all these processes can 
map the same shared library at different addresses, so that is why
a shared library has to work correctly without using any absolute addresses.

Let's do a simple experiment:

\begin{lstlisting}[style=customc]
#include <stdio.h>

int global_variable=123;

int f1(int var)
{
    int rt=global_variable+var;
    printf ("returning %d\n", rt);
    return rt;
};
\end{lstlisting}

Let's compile it in GCC 4.7.3 and see the resulting .so file in \IDA:

\begin{lstlisting}
gcc -fPIC -shared -O3 -o 1.so 1.c
\end{lstlisting}

\begin{lstlisting}[caption=GCC 4.7.3,style=customasmx86]
.text:00000440                 public __x86_get_pc_thunk_bx
.text:00000440 __x86_get_pc_thunk_bx proc near         ; CODE XREF: _init_proc+4
.text:00000440                                         ; deregister_tm_clones+4 ...
.text:00000440                 mov     ebx, [esp+0]
.text:00000443                 retn
.text:00000443 __x86_get_pc_thunk_bx endp

.text:00000570                 public f1
.text:00000570 f1              proc near
.text:00000570
.text:00000570 var_1C          = dword ptr -1Ch
.text:00000570 var_18          = dword ptr -18h
.text:00000570 var_14          = dword ptr -14h
.text:00000570 var_8           = dword ptr -8
.text:00000570 var_4           = dword ptr -4
.text:00000570 arg_0           = dword ptr  4
.text:00000570
.text:00000570                 sub     esp, 1Ch
.text:00000573                 mov     [esp+1Ch+var_8], ebx
.text:00000577                 call    __x86_get_pc_thunk_bx
.text:0000057C                 add     ebx, 1A84h
.text:00000582                 mov     [esp+1Ch+var_4], esi
.text:00000586                 mov     eax, ds:(global_variable_ptr - 2000h)[ebx]
.text:0000058C                 mov     esi, [eax]
.text:0000058E                 lea     eax, (aReturningD - 2000h)[ebx] ; "returning %d\n"
.text:00000594                 add     esi, [esp+1Ch+arg_0]
.text:00000598                 mov     [esp+1Ch+var_18], eax
.text:0000059C                 mov     [esp+1Ch+var_1C], 1
.text:000005A3                 mov     [esp+1Ch+var_14], esi
.text:000005A7                 call    ___printf_chk
.text:000005AC                 mov     eax, esi
.text:000005AE                 mov     ebx, [esp+1Ch+var_8]
.text:000005B2                 mov     esi, [esp+1Ch+var_4]
.text:000005B6                 add     esp, 1Ch
.text:000005B9                 retn
.text:000005B9 f1              endp
\end{lstlisting}

\newcommand{\retstring}{\IT{<<returning \%d\textbackslash{}n>>}}
\newcommand{\globvar}{\IT{global\_variable}}

That's it: the pointers to \retstring{} and \globvar{} are to be corrected at each function execution.

\par The \TT{\_\_x86\_get\_pc\_thunk\_bx()} function returns in \EBX the address of the point after a call to itself (\TT{0x57C} here).

That's a simple way to get the value of the program counter (\EIP) at some point.
The \TT{0x1A84} constant is related to the difference between this function's start and the so-called
\IT{Global Offset Table Procedure Linkage Table} (GOT PLT), the section right after the \IT{Global Offset Table} (GOT), where the pointer to \globvar{} is.
\IDA shows these offsets in their processed form to make them easier to understand, but in fact the code is:

\begin{lstlisting}[style=customasmx86]
.text:00000577                 call    __x86_get_pc_thunk_bx
.text:0000057C                 add     ebx, 1A84h
.text:00000582                 mov     [esp+1Ch+var_4], esi
.text:00000586                 mov     eax, [ebx-0Ch]
.text:0000058C                 mov     esi, [eax]
.text:0000058E                 lea     eax, [ebx-1A30h]
\end{lstlisting}

Here \EBX points to the \TT{GOT PLT} section and to calculate a pointer to \globvar{} (which is stored in 
the \TT{GOT}), \TT{0xC} must be subtracted.

To calculate pointer to the \retstring{} string, \TT{0x1A30} must be subtracted.

\myindex{x86-64}
\myindex{x86!\Registers!RIP}

By the way, that is the reason why the AMD64 instruction set supports RIP\footnote{program counter in AMD64}-relative addressing --- to simplify PIC-code.

Let's compile the same C code using the same GCC version, but for x64.

\myindex{objdump}
\IDA would simplify the resulting code but would suppress the RIP-relative addressing details, 
so we are going to use \IT{objdump} instead of IDA to see everything:

\begin{lstlisting}[style=customasmx86]
0000000000000720 <f1>:
 720:	48 8b 05 b9 08 20 00 	mov    rax,QWORD PTR [rip+0x2008b9]        # 200fe0 <_DYNAMIC+0x1d0>
 727:	53                   	push   rbx
 728:	89 fb                	mov    ebx,edi
 72a:	48 8d 35 20 00 00 00 	lea    rsi,[rip+0x20]        # 751 <_fini+0x9>
 731:	bf 01 00 00 00       	mov    edi,0x1
 736:	03 18                	add    ebx,DWORD PTR [rax]
 738:	31 c0                	xor    eax,eax
 73a:	89 da                	mov    edx,ebx
 73c:	e8 df fe ff ff       	call   620 <__printf_chk@plt>
 741:	89 d8                	mov    eax,ebx
 743:	5b                   	pop    rbx
 744:	c3                   	ret    
\end{lstlisting}

\TT{0x2008b9} is the difference between the address of the instruction at \TT{0x720} and \globvar{}, and 
\TT{0x20} is the difference between the address of the instruction at 
\TT{0x72A} and the \retstring{} string.

As you might see, the need to recalculate addresses frequently makes execution slower 
(it is better in x64, though).

So it is probably better to link statically if you care about performance \InSqBrackets{see: \AgnerFogCPP}.

\subsubsection{Windows}
\myindex{Windows!Win32}

The PIC mechanism is not used in Windows DLLs. If the Windows loader needs to load DLL 
on another base address, it \q{patches} the DLL in memory (at the \IT{FIXUP} places) in order to correct 
all addresses.

This implies that several Windows processes cannot share an once loaded DLL 
at different addresses in different process' memory 
blocks --- since each instance that's loaded in memory is \IT{fixed} to work only at these addresses..

